---
title: 编辑器方法
description: 探索可用于与Plate编辑器交互及自定义的各种方法。
---

本指南涵盖了Plate编辑器实例上可用的各种方法。

## 访问编辑器

访问编辑器实例的方式取决于您需要的上下文。

### Plate组件内部

使用以下钩子之一：

- `useEditorRef`: 永不重新渲染。
- `useEditorSelector`: 仅当特定编辑器属性变化时重新渲染。
- `useEditorState`: 每次变化都重新渲染。

```ts
import { useEditorRef, useEditorSelector, useEditorState } from 'platejs/react';

const MyComponent = () => {
  const editor = useEditorRef();
  const hasSelection = useEditorSelector((editor) => !!editor.selection, []);
  const editorState = useEditorState();
  
  // ...
};
```

#### useEditorRef

- 使用永不替换的编辑器引用。这应该是默认选择。
- 由于编辑器是一个通过引用更新的可变对象，`useEditorRef`总是足以在回调中访问编辑器。
- `useEditorRef`不会导致组件重新渲染，因此是性能最佳的选择。

#### useEditorSelector

- 订阅基于编辑器的特定选择器。这是订阅状态变化最高效的方式。
- 示例用法：`const hasSelection = useEditorSelector((editor) => !!editor.selection, []);`
- 当您希望组件响应特定变化重新渲染时，可以使用`useEditorSelector`访问相关属性。
- 选择器函数在每次编辑器变化时被调用（如每次按键或选择变化），但组件仅在返回值变化时重新渲染。
- 为确保正常工作，返回值应能使用`===`进行比较。通常这意味着返回原始值（数字、字符串或布尔值）。
- 可以为`useEditorSelector`提供自定义的`equalityFn`选项来处理`===`不适用的情况。
- 如果选择器函数依赖局部作用域变量，应将它们包含在依赖项列表中。

#### useEditorState

- 每次编辑器变化时都重新渲染。
- 使用`useEditorState`会导致组件在用户每次按键或改变选择时重新渲染。
- 对于大型文档或重渲染成本较高的情况，可能会引发性能问题。

### Plate组件外部

要在`Plate`组件外部访问编辑器或处理多个编辑器，使用`PlateController`组件：

```ts
import { PlateController } from 'platejs/react';

const App = () => (
  <PlateController>
    <Toolbar />
    <MyEditor />
  </PlateController>
);

const Toolbar = () => {
  const editor = useEditorState();
  const isMounted = useEditorMounted();
  // 在此使用编辑器方法
};
```

`PlateController`管理活动编辑器：
- 默认第一个挂载的编辑器为活动状态（可通过`Plate`上的`primary={false}`覆盖）。
- 焦点改变会切换活动编辑器。
- 编辑器保持活动状态直到另一个编辑器获得焦点或自身卸载。

`PlateController`内部的钩子如`useEditorRef`和`useEditorSelector`会与活动编辑器交互。若无活动编辑器，它们会返回一个回退编辑器，该编辑器：
- 为查询提供默认值。
- 不可被修改。
- 在状态变更操作时抛出错误。

回退编辑器场景：
- 没有挂载的`Plate`组件。
- 所有`Plate`组件都标记为非主要。
- 在`PlateContent`挂载过程中。

可使用`useEditorMounted`检查是否有编辑器已挂载：

```ts
const Toolbar = () => {
  const editor = useEditorState();
  const isMounted = useEditorMounted();
  
  if (!isMounted) {
    return <div>编辑器未就绪</div>;
  }
  
  return <div>{/* 工具栏内容 */}</div>;
};
```

也可通过`editor.meta.isFallback`检查是否为回退实例。

## API方法

### findPath

查找节点的路径。默认为`findNodePath`（遍历）。被`withPlate`覆盖为使用`ReactEditor.findPath`（记忆化）。

```ts
const path = editor.findPath(node);
```

### getApi

获取编辑器的类型化API：

```ts
const api = editor.getApi(TablePlugin);
api.api.create.tableCell(); // 类型安全的API方法
```

### getTransforms

获取编辑器的类型化转换方法：

```ts
const tf = editor.getTransforms(TablePlugin);
tf.insert.tableRow(); // 类型安全的转换方法
```

## 插件方法

### getPlugin

通过键或基础插件获取编辑器插件实例：

```ts
const codeBlockPlugin = editor.getPlugin(CodeBlockPlugin);
const headingPlugin = editor.getPlugin({ key: KEYS.heading });
```

### getType

获取与插件关联的节点类型：

```ts
const paragraphType = editor.getType(KEYS.p);
```

## 选项方法

### getOption

获取插件的特定选项值：

```ts
const search = editor.getOption(FindReplacePlugin, 'search');
```

要订阅选项变化，可使用`usePluginOption`或`usePluginOptions`钩子。

### getOptions

获取插件的所有选项：

```ts
const linkOptions = editor.getOptions(LinkPlugin);
```

### setOption

设置插件的特定选项值：

```ts
editor.setOption(FindReplacePlugin, 'search', 'hello');
```

### setOptions

设置插件的多个选项：

```ts
editor.setOptions(FindReplacePlugin, {
  search: 'hello',
  caseSensitive: true,
});
```

也可使用Immer函数更新选项：

```ts
editor.setOptions(FindReplacePlugin, (draft) => {
  draft.search = 'hello';
  draft.caseSensitive = true;
});
```

### getOptionsStore

获取插件的[zustand-x](https://github.com/udecode/zustand-x)选项存储：

```ts
const store = editor.getOptionsStore(FindReplacePlugin);
```